import {RGBAImage, AlphaImage} from "../util/Image";

export class Texture {
  gl: WebGLRenderingContext;
  size: Array<number>;
  texture: WebGLTexture | null;
  format: number;
  filter?: number;
  wrap?: number;

  /**
   * Creates an instance of Texture.
   * @param {WebGLRenderingContext} gl
   * @param {(RGBAImage | AlphaImage)} image
   * @param {gl.RGBA | gl.ALPHA} format
   * @memberof Texture
   */
  constructor(gl: WebGLRenderingContext, image: RGBAImage | AlphaImage, format: number) {
      this.gl = gl;

      const {width, height} = image;
      this.size = [width, height];
      this.format = format;

      this.texture = gl.createTexture();
      this.update(image);
  }

  update(image: RGBAImage | AlphaImage) {
    const {width, height, data} = image;
    this.size = [width, height];

    const {gl} = this;
    gl.bindTexture(gl.TEXTURE_2D, this.texture);
    gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);

    if (this.format === gl.RGBA) {
      gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
    }

    gl.texImage2D(gl.TEXTURE_2D, 0, this.format, width, height, 0, this.format, gl.UNSIGNED_BYTE, data);
  }

  /**
   * @param {gl.LINEAR | gl.NEAREST} filter
   * @param {gl.REPEAT | gl.CLAMP_TO_EDGE | gl.MIRRORED_REPEAT} wrap
   * @memberof Texture
   */
  bind(filter: number, wrap: number) {
    const {gl} = this;
    gl.bindTexture(gl.TEXTURE_2D, this.texture);

    if (filter !== this.filter) {
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);
      this.filter = filter;
    }

    if (wrap !== this.wrap) {
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrap);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrap);
      this.wrap = wrap;
    }
  }

  destroy() {
    const {gl} = this;
    gl.deleteTexture(this.texture);
    this.texture = null;
  }
}